﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MapLibrary.Players.CollisionResponse
{
    /// <summary>
    /// A CollisionAction is a collection of CollisionBehaviors that will be triggered
    /// when the CollisionAction is triggered.  A CollisionAction is mapped to a unique
    /// CollisionCategory, and will be triggered when the Sprite owning the CollisionAction
    /// collides with another Sprite with the proper CollisionCategory.
    /// </summary>
    public class CollisionAction
    {
        private CollisionResponseManager.CollisionCategory categoryMapping;
        private List<CollisionBehavior> behaviors;
        private bool collisionResolution;

        public CollisionAction(CollisionResponseManager.CollisionCategory mapping, bool willColHappen)
        {
            categoryMapping = mapping;
            collisionResolution = willColHappen;

            behaviors = new List<CollisionBehavior>();
        }

        /// <summary>
        /// Update this CollisionAction with all of the collision categories the Sprite collided
        /// with this frame.  This will in turn update all of the CollisionBehavior's that are
        /// owned by this CollisionAction.
        /// 
        /// The behaviors are all updated with a boolean parameter that represents whether or not
        /// the Sprite was in contact with another Sprite whose category is contained in one of
        /// the cateogiresTriggered this frame.
        /// </summary>
        /// <param name="categoriesTriggered"></param>
        public void Update(List<CollisionResponseManager.CollisionCategory> categoriesTriggered)
        {
            bool contained = isElementOfOne(categoriesTriggered);

            foreach (CollisionBehavior behavior in behaviors)
            {
                behavior.Update(contained);
            }
        }

        /// <summary>
        /// Whether or not the collision should be solved by the physics
        /// engine.  True means solve the collision, false means ignore
        /// the collision.
        /// </summary>
        public bool CollisionResolution
        {
            get { return collisionResolution; }
        }

        /// <summary>
        /// The List of CollisionBehaviors associated with this
        /// CollisionAction.
        /// </summary>
        public List<CollisionBehavior> Behaviors
        {
            get { return behaviors; }
        }

        /// <summary>
        /// Check if the category that this CollisionAction is mapped to is contained in one
        /// of the categories in the passed list of CollisionCategorys.
        /// 
        /// For example, suppose CollisionCategory.Enemy was contained in categoriesTriggered,
        /// and this CollisionAction is mapped to CollisionCategory.Tuberulcosis.  Then this
        /// method would return true.  On the other hand, if CollisionCategory.Malaria as the only
        /// element of categoriesTriggered, and this CollisionAction is mapped to CollisionCategory.Tuberulcosis,
        /// this method would return false.
        /// </summary>
        /// <param name="categoriesTriggered"></param>
        /// <returns></returns>
        private bool isElementOfOne(List<CollisionResponseManager.CollisionCategory> categoriesTriggered)
        {
            foreach(CollisionResponseManager.CollisionCategory category in categoriesTriggered)
            {
                if ((categoryMapping & category) != 0)
                    return true;
            }
            return false;
        }
    }
}
